package com.tbit.uqbike.service.rpcservice.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.tbit.uqbike.constant.BrandConfig;
import com.tbit.uqbike.constant.*;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.OrderInfo;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.MQProducer;
import com.tbit.uqbike.service.base.MachineService;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.service.rpcservice.MachineBorrowService;
import com.tbit.uqbike.webmanager.controller.BaseController;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.history.HistoryDao;
import com.tbit.uqbike.webmanager.dao.capital.RideUseLogDao;
import com.tbit.uqbike.webmanager.util.*;
import com.tbit.utils.DateTimeUtil;
import com.tbit.utils.NullUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("machineBorrowService")
@Slf4j
public class MachineBorrowServiceImpl implements MachineBorrowService {
    @Autowired
    private MachineBorrowDao machineBorrowDao;
    @Autowired
    private UserService userService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private ParkService parkService;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private UserAccountLogService userAccountLogService;
    @Autowired
    private GiftCardUserService giftCardUserService;
    @Autowired
    private HistoryDao historyDao;
    @Autowired
    private TerControlService terControlService;
    @Autowired
    private GeoReMachineDao geoReMachineDao;
    @Autowired
    private MQProducer mQProducer;
    @Autowired
    private BrandRemoteConfigDao brandRemoteConfigDao;
    @Autowired
    private UserDelayPayDao userDelayPayDao;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Autowired
    private RechargeDao rechargeDao;
    @Autowired
    private ParkPointDao parkPointDao;
    @Autowired
    private RideUseLogDao rideUseLogDao;

    public static void main(String[] args) {
    }

    @Override
    public MachineBorrow getByMachineId(Integer machineId) {
        return machineBorrowDao.getByMachineId(machineId);
    }

    @Override
    public List<MachineBorrow> getByAccountId(Integer accountId) {
        return machineBorrowDao.getByAccountId(accountId);
    }

    @Override
    public List<MachineBorrow> getAll() {
        return machineBorrowDao.getAll();
    }

    @Override
    public MachineBorrow getByUserId(Integer userId) {
        return machineBorrowDao.getByUserId(userId);
    }

    @Override
    public void del(Integer machineId) {
        machineBorrowDao.del(machineId);
    }

    @Override
    public void finishRideOrder(LoginInfo loginInfo, Integer accountId, String phone, String machineNO, Integer money, String remark) {
        Integer userType = loginInfo.type;
        MachineBorrow machineBorrow = null;
        Machine machine = null;
        /**判断是根据用户手机号码还是设备编号结束*/
        if (phone != null) {
            /**查询用户信息*/
            User user = userService.getByAdaccountId(accountId, phone);
            if (user == null) {
                throw new BaseException(SystemCodeEnum.USER_NOT_EXIST);
            }
            machineBorrow = getByUserId(user.getUserId());

            if (machineBorrow == null) {
                throw new BaseException("machine_borrow_not_exist");
            }

            machine = machineService.getByMachineId(machineBorrow.getMachineId());
        } else if (machineNO != null) {
            /**查询设备信息*/
            machine = machineService.getByMachineNO(machineNO);
            if (machine == null) {
                throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
            }
            machineBorrow = getByMachineId(machine.getMachineId());
        }

        /**判断是否有操作的权限*/
        if (UserConstant.USER_AGENT.equals(userType) && !machine.getAccountId().equals(accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        } else if (UserConstant.USER_FRANCHISEE.equals(userType)) {
            if (!accountId.equals(machine.getAccountId())) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }

        finishRideOrderM(machine.getUserCode(), money, remark);

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserCode(machine.getUserCode());
        orderInfo.setParamName(ControlTypeConstant.CONTROL_TYPE_LOCK);
        orderInfo.setControlType(ControlTypeConstant.CONTROL_TYPE_CONTROL);
        orderInfo.setDesc(BaseController.getLogin(ServletUtils.getRequest()).context.getMessage("manually_end_the_order"));
        orderInfo.setBusinessCode(null);

        terControlService.sendControl(loginInfo, orderInfo);

//        OrderLog orderLog = null;
//        try {
//            // 插入日志
//            orderLog = OrderInfo.parseOrderLog(orderInfo);
//            orderLog.setOptype(loginInfo.type);
//            orderLog.setOpid(loginInfo.id);
//            orderLogDao.insert(orderLog);
//        } catch (Exception e) {
//            log.error(String.format("插入指令日志失败:%s", JSONObject.toJSONString(e)));
//        }

    }

    @Override
    public void finishRideOrderM(String userCode, Integer money, String remark) {
        MachineBorrow machineBorrow = null;
        /**判断是根据用户手机号码还是设备编号结束*/
        /**查询设备信息*/
        Machine machine = machineService.getByUserCode(userCode);
        if (machine == null) {
            throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
        }
        machineBorrow = getByMachineId(machine.getMachineId());

        if (machineBorrow == null) {
            throw new BaseException(SystemCodeEnum.MACHINE_BORROW_NOT_EXIST);
        }
        Date nowDate = new Date();

        Map<String, Object> param = new HashMap<>();
        param.put("machineId", machineBorrow.getMachineId());
        param.put("functionType", MachineStateConstant.MACHINE_TYPE_HELMAT);

        /**查询用户信息*/
        User user = userService.getByUserId(machineBorrow.getUserId());
        if (user == null) {
            throw new BaseException(SystemCodeEnum.USER_NOT_EXIST);
        }
        boolean flag = true;
        try {
            if (rechargeDao.selectPayGradesCountByUserId(user.getUserId()) > 0) {
                //用户有支付分订单
                String url = OperaPswConstant.ACCOUNT_OPERA_PUSH_URL + ServiceUrlConstant.CLIENT_END_ORDER;
                String paramA = "youqu";
                long date = System.currentTimeMillis();
                String sign = MD5PasswordUtil.MD5("TBIT" + date + paramA);
                Map<String, Object> paramMap = new HashMap<>(8);
                paramMap.put("userId", user.getUserId());
                paramMap.put("money", money);
                paramMap.put("date", date);
                paramMap.put("param", paramA);
                paramMap.put("sign", sign);
                log.info(String.format("支付分结束订单，调用客户端接口：%s,参数：%s", url, JSON.toJSONString(paramMap)));
                HttpResponse response = HttpRequest.get(url).form(paramMap).execute();
                log.info(String.format("支付分结束订单客户端接口返回：%s", response.body()));
                if (Objects.equals("true", JSON.parseObject(response.body()).get("data").toString())) {
                    flag = false;
                    //成功的要单独给用户扣掉这个钱，因为是充值订单，所以客户端结束支付分订单后会给他充值对应的钱
                    if (money > 0) {
                        log.info("支付分结束订单，扣除用户余额:{}", money);
                        userService.updateMoney(user.getUserId(), -money, null);
                    }
                    UserAccountLog userAccountLog = new UserAccountLog(user.getUserId(), machine.getAccountId(), 0, 0, money, new Date(), "支付分订单扣款");
                    userAccountLogService.insert(userAccountLog);
                }
            }
        } catch (Exception e) {
            log.error("调用客户端接口支付分结束订单失败");
            log.error(e.getMessage(), e);
        }
        /**给用户的欠款字段赋值*/
        if (NullUtils.isEmpty(user.getRideMoney())) {
            user.setRideMoney(0);
        }


        /**删除临时停车记录*/
        Park park = parkService.getByMachineId(machineBorrow.getMachineId());
        if (park != null) {
            /**删除临时停车记录*/
            parkService.delByUserId(park.getUserId());
            /**记录日志*/
            park.setEndtime(nowDate);
            parkService.addLog(park);
        }

        /**删除当前骑行记录*/
        del(machineBorrow.getMachineId());
        RideLog rideLogDB1 = rideLogService.getByOrderNO(machineBorrow.getOrderNO());
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("machineNO", machine.getMachineNO());
        params.put("startTime", rideLogDB1.getStartTime());
        params.put("endTime", DateTimeUtil.getNowTime());
        /**骑行里程*/
        Integer mileage = historyDao.getMileageByMachineNOAndTime(params);
        if (mileage == null) {
            mileage = 0;
        }
        //米转公里;
        double mileageDB = (double) mileage / 1000;
        /**非调度还车才可以使用礼品卡余额*/
        /**存在超时结束订单调度费*/
        Integer disMoney = 0;
        Integer debtMoney = user.getRideMoney();
        if (remark != null && remark.contains("系统超时自动结束订单,调度还车")) {
            disMoney = new Double((Double.parseDouble(remark.substring(remark.lastIndexOf("调度费用=") + 5)) * 100)).intValue();
        }
        if (!flag) {
            remark = remark + "，支付分结束订单";
        }
        /**扣费金额大于0，记录用户资金变动日志*/
        if (money > 0 && flag) {
            /**获取这个品牌的是否扣除本金开关配置*/
            List<BrandRemoteConfig> brandRemoteConfigList = brandRemoteConfigDao.selectBrandRemoteConfigList(new BrandRemoteConfig(user.getAccountId(), BrandConfig.BRAND_CASH_TYPE));
            Integer giftCardMoney = 0;
            Integer value = 0;
            if (!NullUtils.isEmpty(brandRemoteConfigList)) {
                String paramKV = brandRemoteConfigList.get(0).getParamKV();
                /**获取配置的value*/
                value = Integer.parseInt(StringUtil.getStrByLocation(paramKV, "="));
            }
            /**获取用户礼品卡金额*/
            GiftCardUser giftCardUser = giftCardUserService.getByUser(machine.getAccountId(), user.getUserId());
            if (BrandConfig.BRAND_CASH_TYPE_GIFTCARD.equals(value)) {
                /**优先扣除礼品卡*/
                /**查询用户当前运营区域的礼品卡余额*/
                if (giftCardUser != null) {
                    if (giftCardUser.getMoney() > 0) {
                        if (giftCardUser.getMoney() < money) {
                            giftCardMoney = giftCardUser.getMoney();
                            money = money - giftCardMoney;
                        } else {
                            giftCardMoney = money;
                            money = 0;
                        }

                        /**更新金额*/
                        giftCardUserService.updateMoney(machine.getAccountId(), user.getUserId(), -giftCardMoney);
                        /**添加扣费日志*/
                        UserAccountLog userAccountLog = new UserAccountLog();
                        userAccountLog.setAccountId(machine.getAccountId());
                        userAccountLog.setUserId(machineBorrow.getUserId());
                        //礼品卡余额
                        userAccountLog.setMoneyType(1);
                        //扣费
                        userAccountLog.setType(0);
                        userAccountLog.setMoney(giftCardMoney);
                        userAccountLog.setOperaTime(nowDate);
                        userAccountLog.setRemark(remark);
                        userAccountLogService.insert(userAccountLog);
                    }
                }
                /**礼品卡不够支付由余额支付*/
                if (money > 0) {
                    Integer userMoney = 0;
                    if (money > user.getMoney()) {
                        debtMoney += money;
                    } else {
                        userMoney = money;
                    }
                    /**更新用户金额,管理平台允许后付费*/
                    userService.updateMoney(machineBorrow.getUserId(), -userMoney, debtMoney);
                    /**添加金额变动日志*/
                    UserAccountLog userAccountLog = new UserAccountLog();
                    userAccountLog.setAccountId(machine.getAccountId());
                    userAccountLog.setUserId(machineBorrow.getUserId());
                    //个人余额
                    userAccountLog.setMoneyType(0);
                    //扣费
                    userAccountLog.setType(0);
                    userAccountLog.setMoney(money);
                    userAccountLog.setOperaTime(nowDate);
                    userAccountLog.setRemark(remark);
                    userAccountLogService.insert(userAccountLog);
                }
            } else if (BrandConfig.BRAND_CASH_TYPE_MONEY.equals(value)) {

                if (giftCardUser != null) {
                    giftCardMoney = giftCardUser.getMoney();
                }

                if (disMoney > 0) {
                    /**用户余额够扣费用*/
                    if (user.getMoney() >= money) {
                        giftCardMoney = 0;
                    } else {
                        /**余额扣完后，礼品卡够扣*/
                        if (giftCardMoney > money - user.getMoney()) {
                            giftCardMoney = money - user.getMoney();
                            money = user.getMoney();
                        } else {
                            money = money - giftCardMoney;
                        }
                    }
                } else {
                    /**订单没有调度费*/
                    /**用户余额不够扣骑行费用*/
                    if (user.getMoney() < money) {
                        /**用户余额不够扣骑行费用*/
                        /**礼品卡的余额够扣剩余部分骑行费用*/
                        if (giftCardMoney >= money - user.getMoney()) {
                            giftCardMoney = money - user.getMoney();
                            money = user.getMoney();
                        } else {
                            /**礼品卡的余额不够扣剩余部分骑行费用，还有部分费用将用户余额变负数*/
                            money = money - giftCardMoney;
                        }
                    } else {
                        giftCardMoney = 0;
                    }
                }

                if (giftCardMoney != 0) {
                    /**更新金额*/
                    giftCardUserService.updateMoney(machine.getAccountId(), user.getUserId(), -giftCardMoney);
                    /**添加扣费日志*/
                    UserAccountLog userAccountLog = new UserAccountLog();
                    userAccountLog.setAccountId(machine.getAccountId());
                    userAccountLog.setUserId(machineBorrow.getUserId());
                    //礼品卡余额
                    userAccountLog.setMoneyType(1);
                    //扣费
                    userAccountLog.setType(0);
                    userAccountLog.setMoney(giftCardMoney);
                    userAccountLog.setOperaTime(nowDate);
                    userAccountLog.setRemark(remark);
                    userAccountLogService.insert(userAccountLog);
                    remark = remark + "，礼品卡消费=" + giftCardMoney / 100.0;
                }
                if (money != 0) {
                    Integer userMoney = 0;
                    if (money > user.getMoney()) {
                        debtMoney += money;
                        userMoney = 0;
                    } else {
                        userMoney = money;
                    }

                    /**更新用户金额,管理平台允许后付费*/
                    userService.updateMoney(machineBorrow.getUserId(), -userMoney, debtMoney);
                    /**添加金额变动日志*/
                    UserAccountLog userAccountLog = new UserAccountLog();
                    userAccountLog.setAccountId(machine.getAccountId());
                    userAccountLog.setUserId(machineBorrow.getUserId());
                    //个人余额
                    userAccountLog.setMoneyType(0);
                    //扣费
                    userAccountLog.setType(0);
                    userAccountLog.setMoney(money);

                    userAccountLog.setOperaTime(nowDate);
                    userAccountLog.setRemark(remark);
                    userAccountLogService.insert(userAccountLog);
                    remark = remark + "，用户余额消费=" + money / 100.0;
                }

            }


        }

        /**更新骑行日志*/
        RideLog rideLog = new RideLog();
        rideLog.setUserid(machineBorrow.getUserId());
        rideLog.setEndtime(nowDate);
        //只记录扣个人余额的费用，礼品卡的费用计算到骑行费用
        rideLog.setMoney(money);
        rideLog.setRemark(remark);
        rideLog.setMileage(mileageDB);
        rideLog.setOrderno(machineBorrow.getOrderNO());
        rideLog.setRegionId(geoReMachineDao.getRegionId(machine.getMachineId()));
        log.info("骑行订单详情:" + JSON.toJSONString(rideLog));
        rideLogService.update(rideLog);


        /**扣费完成的金额大于0，说明够钱支付，更新支付时间*/
        User userNew = userService.getByUserId(machineBorrow.getUserId());
        //支付分结束订单的直接算是成功结束
        if ((userNew != null && userNew.getMoney() >= 0 && debtMoney == 0) || !flag) {
            RideLog rideLogDB = new RideLog();
            rideLogDB.setOrderno(machineBorrow.getOrderNO());

            rideLogDB.setPaytime(nowDate);
            rideLogService.updatePayTime(rideLogDB);
            UserDelayPay userDelayPay = new UserDelayPay(rideLog.getUserId(), rideLogDB1.getAccountId(), rideLog.getMoney(), new Date(), rideLog.getOrderNO());
            userDelayPayDao.insert(userDelayPay);
            //骑行订单详情
            rideUseLogDao.insert(new RideUseLog(null, rideLog.getOrderNO(), rideLogDB1.getAccountId(), user.getAccountId(), rideLog.getMoney(), rideLog.getMoney(), 0, 0, 0, null, nowDate, null));
        }
        //查询区域配置
        List<AccountConfigExt> accountConfigExts = accountConfigExtDao.selectAccountConfigExtList(rideLogDB1.getAccountId(), AppPushUtil.ACCOUNTCONFIG_MODEL);
        //服务推送通知开关
        if (accountConfigExts.size() > 0 && Objects.equals(accountConfigExts.get(0).getParamValue(), "1")) {
            //发送小程序通知
            AppPushUtil.sendLockMsg(user.getAccountId(), user.getUserId(), new AppPushParam(rideLogDB1.getStartTime(), nowDate, "欢迎下次再次骑行！").initParam(), AppPushUtil.TEMPLATE_TYPE_LOCK);
        }


        try {
//        /**订单信息给运维端端推送*/
            ParkPoint parkPoint = parkPointDao.getByParkPointId(rideLogDB1.getEndPointId());
            Map<String, Object> rabbitMap = new HashMap<>();
            if (!NullUtils.isEmpty(parkPoint)) {
                rabbitMap.put("lat", parkPoint.getLaC());
                rabbitMap.put("lon", parkPoint.getLoC());
            }
            rabbitMap.put("accountId", machine.getAccountId());
            rabbitMap.put("cycling_mile", mileageDB);
            rabbitMap.put("fee", money);
            rabbitMap.put("machineNO", machine.getMachineNO());
            rabbitMap.put("orderNO", rideLogDB1.getOrderNO());
            rabbitMap.put("phone", user.getPhone());
            rabbitMap.put("return_time", new Date());
            rabbitMap.put("type", "1");
            rabbitMap.put("userCode", userCode);
            //没调度费传1，有调度费传4
            rabbitMap.put("orderType", disMoney == 0 ? 1 : 4);
            /**发送到MQ*/
            log.info("订单消息推送运维端{}", JSON.toJSONString(rabbitMap));
            mQProducer.sendDataToQueue("tbit_uqbike_ride_push", RabbitMQData.routeKey, GatewayProtocol.MQ_MSG_ID_MAIM_PUSH, rabbitMap);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    @Override
    public void order() {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", "100279");
        map.put("cycling_mile", "1.1");
        map.put("fee", "200");
        map.put("lat", "33.07421166666666");
        map.put("lon", "107.02407");
        map.put("machineNO", "009210060");
        map.put("orderNO", "202108318055147216");
        map.put("phone", "18829578981");
        map.put("return_time", "2021-09-01 00:03:11");
        map.put("type", "1");
        map.put("userCode", "00213330");


        /**发送到MQ*/
        mQProducer.sendDataToQueue("tbit_uqbike_ride_push", RabbitMQData.routeKey, GatewayProtocol.MQ_MSG_ID_CONTROL_TER, map);

    }

    @Override
    public List<MachineBorrow> getByMachineIds(List<Integer> machineIds) {
        return CollUtil.isEmpty(machineIds) ?
                Collections.emptyList() :
                machineBorrowDao.getByMachineIds(StringUtil.getListString(machineIds));
    }

}